<template>
    <div class="goods-sku">
      <dl v-for="goodsOption in goodsSpecOptions" :key="goodsOption.id">
          <dt>{{ goodsOption.name }}</dt>
          <dd>
              <template v-for="(item,index) in goodsOption.values" :key="index">
                  <div :class="{selected:item.selected, disabled:item.disabled}" @click="clickSpecs(goodsOption,item)">
                    <img v-if="item.img_url" :src="global.FILE_DOMAIN + item.img_url" alt="">
                    <span>{{item.val}}</span>
                  </div>
              </template>
          </dd>
      </dl>
    </div>
  </template>
  
  
  
<script setup>
import { computed, onMounted, inject } from "vue"
import getPowerSet from '@/utils/power-set'

// 获取全局对象
const global = inject('global')
  
const props = defineProps({
    goodsOptions: {
        type: Array,
        default: () => []
    },
    goodsSkus: {
        type: Array,
        default: () => []
    },
    skuId: {
      type: Number,
      default: ''
    },
    goodsSkuImg: {
      type: String,
      default: ''
    }
})
  
// 初始化选中状态
const initSelectedStatus = (goodsSkus, skuId) => {
  const sku = goodsSkus.find(sku => sku.id === skuId)
  if (sku) {
    goodsSpecOptions.value.forEach((spec, i) => {
      const value = sku.spec_option_value_items[goodsSpecOptions.value.length-i-1]
      spec.values.forEach(item => {
        item.selected = item.val === value
      })
    })
  }
}
  
// 商品规格选项计算属性
const goodsSpecOptions = computed(() => {
    let goodsSpecOptionItems = []
    props.goodsOptions.forEach(item => {
      if (item.value) {
        let values = item.value.split(',')
        let valueItems = []
        values.forEach(val => {
          let goodsSkuImg = ''
          if (props.goodsOptions.length == 1 || item.is_img) {
            props.goodsSkus.forEach((goodsSku) => {
              if (goodsSku.spec_option_value_items.includes(val)) {
                goodsSkuImg = goodsSku.img_url
              }
            })
          }

          valueItems.push({'val': val, 'img_url': goodsSkuImg})
        });

        item.values = valueItems
        goodsSpecOptionItems.push(item)
      }
    });

    return goodsSpecOptionItems
})
  
// 点击选择商品规格选项
const emit = defineEmits(['change'])
const clickSpecs = (item, val) => {
  // 如果是禁用状态不作为
  if (val.disabled) {
    return
  }

  // 1. 选中与取消选中逻辑
  if (val.selected) {
      val.selected = false
  } else {
      item.values.forEach(bv => { bv.selected = false })
      val.selected = true
  }

  // 点击的时候更新禁用状态
  updateDisabledStatus(goodsSpecOptions)

  // 触发change事件将sku数据传递出去
  const selectedArr = getSelectedArr(goodsSpecOptions).filter(v => v)
  if (selectedArr.length === goodsSpecOptions.value.length) {
    const selectedArrFilter = selectedArr.filter(v => v).reverse()
    const skuIds = pathMap[selectedArrFilter.join(spliter)]
    const sku = props.goodsSkus.find(sku => sku.id === skuIds[0])
    // 传递
    emit('change', {
      skuId: sku.id,
      price: sku.price,
      inventory_num: sku.inventory_num,
      cover_url: sku.img_url != '' ? sku.img_url : props.goodsSkuImg,
      specsText: sku.spec_option_values.reduce((p, n) =>`${p} ${n.name}：${n.value}`, '').replace(' ', '')
    })
  } else {
    emit('change', {})
  }
}
  
  
const spliter = '★'
const pathMap = {}
// 根据skus数据得到路径字典对象
const getPathMap = (goodsSkus) => {
  goodsSkus.forEach(sku => {
    // 1. 过滤出有库存有效的sku
    if (sku.inventory_num > 0) {
      // 2. 得到sku属性值数组的子集
      const powerSet = getPowerSet(sku.spec_option_value_items)
      // 4. 设置给路径字典对象
      powerSet.forEach(set => {
        const key = set.join(spliter)
        if (pathMap[key]) {
          // 已经有key往数组追加
          pathMap[key].push(sku.id)
        } else {
          // 没有key设置一个数组
          pathMap[key] = [sku.id]
        }
      })
    }
  })
}

// 得到当前选中规格集合
const getSelectedArr = (specOptions) => {
  const selectedArr = []
  specOptions.value.forEach(spec => {
    const selectedVal = spec.values.find(val => val.selected)
    selectedArr.push(selectedVal ? selectedVal.val : undefined)
  })
  return selectedArr
}

// 更新按钮的禁用状态
const updateDisabledStatus = (specOptions) => {
  specOptions.value.forEach((spec, i) => {
    const selectedArr = getSelectedArr(specOptions)
    spec.values.forEach(item => {
      // 已经选中的按钮不用判断
      if (item.selected) {
        return false
      }
      // if (item.val === selectedArr[i]) return false
      // 未选中的替换对应的值
      selectedArr[i] = item.val
      // 剔除undefined数据，按照分隔符拼接key【注意过滤数组需要反转才能拼接】
      const selectedArrFilter = selectedArr.filter(v => v).reverse()
      const key = selectedArrFilter.join(spliter)
      // 设置禁用状态
      item.disabled = !pathMap[key]
    })
  })
}

onMounted(() => {
  getPathMap(props.goodsSkus)
  
  // 组件初始化的时候更新禁用状态
  updateDisabledStatus(goodsSpecOptions)

  // 根据传入的skuId默认选中规格按钮
  initSelectedStatus(props.goodsSkus, props.skuId)
})
</script>
  
  
<style scoped lang="scss">  
@mixin sku-state-mixin () {
    border: 1px solid #e4e4e4;
    margin-right: 10px;
    cursor: pointer;
    &.selected {
      border-color: $main-color;
      background-color: #D6FCF5;
    }
    &.disabled {
      opacity: 0.6;
      border-style: dashed;
      cursor: not-allowed;
    }
  }
  .goods-sku {
    padding-left: 10px;
    padding-top: 20px;
    dl {
      display: flex;
      padding-bottom: 20px;
      align-items: center;
      dt {
        width: 80px;
        color: #999;
      }
      dd {
        flex: 1;
        color: #666;
        display: flex;
        flex-wrap: wrap;
        div {
          display: flex;
          align-items: center;
          padding: 4px 10px;
          margin: 4px;
          @include sku-state-mixin;
          img {
            width: 50px;
            height: 50px;
            @include sku-state-mixin;
          }
          span {
            line-height: 20px;
          }
        }
      }
    }
  }
  </style>